﻿using IService.Admin;
using Model.Enums.Admin;
using Model.Parameter.Admin;
using Model.Result.Admin;

namespace Service.Admin
{
    public class AdminService : BaseService<TAdminInfo>, IAdminService
    {
        private readonly IOptions<JwtConfig> _Config;
        private readonly IAdminPermissionService _adminPermissionService;
        private readonly WebMiscConfig _WebMiscConfig;

        public AdminService(IOptions<JwtConfig> cg, IOptions<WebMiscConfig> wg, IUnitOfWorkService se, IAdminPermissionService adminPermissionService) : base(se)
        {
            _WebMiscConfig = wg.Value;
            _Config = cg;
            _adminPermissionService = adminPermissionService;
        }

        #region 用户登录相关

        public async Task<RM_ApiResult> AdminLogin(Par_AdminLogin par)
        {
            if (string.IsNullOrEmpty(par.AdminName) || string.IsNullOrEmpty(par.AdminPwd))
            {
                return _ResultHelper.BuildError(Enum_SysAttributeType.Admin.LoginEmpty, null);
            }

            var password = md5Helper.CalculateMD5Hash(par.AdminPwd);

            if (await Any(o => o.AdminName == par.AdminName && o.AdminPwd == password))
            {
                if (await Any(o => o.AdminName == par.AdminName && o.Status == (int)Enum_AdminStatus.Stop))
                {
                    return _ResultHelper.BuildError(Enum_SysAttributeType.Admin.LoginStop, null);
                }

                var admin = await Get(o => o.AdminName == par.AdminName);

                if (!admin.IsSuper && !await Any<TAdminpermissionrelation>(o => o.AdminId == admin.Id))
                {
                    return _ResultHelper.BuildError(Enum_SysAttributeType.Admin.PowerNo, null);
                }

                if (!string.IsNullOrEmpty(admin.Token))
                {
                    _Redis.DeleteRedisAttr("en", admin.Token, Enum_RedisKey.AdminToken);
                }

                admin.LastLoginDate = DateTime.Now;
                admin.Token = Guid.NewGuid().ToString();
                admin.ExpireTime = DateTime.Now.AddSeconds(_Config.Value.ExpireTime);

                await Update(admin, o => new { o.LastLoginDate, o.LastLoginIp, o.Token, o.ExpireTime });

                //模糊敏感数据
                admin.AdminPwd = "";
                //添加redis缓存
                _Redis.SetRedisAttr("en", admin.Token, admin, (DateTime)admin.ExpireTime, Enum_RedisKey.AdminToken);

                var result = new RM_AdminLogin { Token = "", User = admin, ExpireAt = (DateTime)admin.ExpireTime, Msg = BuildWelcomeMsg() };

                #region 权限

                //if (await _DbContext.Queryable<TAdminInfo>().AnyAsync(o => o.IsSuper && o.AdminName == par.AdminName))
                //{
                //    //超级管理员
                //    result.Permissions = await _DbContext.Queryable<TPermission>()
                //                                         .Select(o => new RM_AdminPermission
                //                                         {
                //                                             Id = o.AuthName.ToLower()
                //                                         }).ToListAsync();
                //}
                //else
                //{
                //    result.Permissions = await _DbContext.Queryable<TAdminpermissionrelation>().LeftJoin<TPermission>((t1, t2) => t1.PermissionId == t2.Id)
                //                                         .Where((t1, t2) => t1.AdminId == par.Id)
                //                                         .Select((t1, t2) => new RM_AdminPermission
                //                                         {
                //                                             Id = t2.AuthName.ToLower()
                //                                         }).ToListAsync();
                //}

                ////添加权限缓存
                //_Redis.SetRedisAttr(par.Token, result.Permissions, (DateTime)par.ExpireTime, Enum_RedisKey.AdminPowers);

                #endregion 权限

                return _ResultHelper.BuildSuccess(result);
            }
            else
            {
                return _ResultHelper.BuildError(Enum_SysAttributeType.Admin.LoginError, null);
            }
        }

        public async Task<RM_ApiResult> AdminLogout()
        {
            if (_CurrentAdmin != null)
            {
                await Update(_CurrentAdmin.Id, o => new TAdminInfo { ExpireTime = DateTime.Now });

                //删除用户redis
                _Redis.DeleteRedisAttr("en", _CurrentAdmin.Token, Enum_RedisKey.AdminToken);
                //删除权限redis
                _Redis.DeleteRedisAttr("en", _CurrentAdmin.Token, Enum_RedisKey.AdminPowers);
            }
            return _ResultHelper.BuildSuccess();
        }

        /// <summary>
        /// 欢迎语
        /// </summary>
        /// <returns></returns>
        private string BuildWelcomeMsg()
        {
            var hours = DateTime.Now.Hour;
            string ts;
            if (hours >= 5 && hours < 10)
            {
                ts = _Redis.GetI18nValue(Enum_SysAttributeType.Time.Morining);
            }
            else if (hours >= 10 && hours < 13)
            {
                ts = _Redis.GetI18nValue(Enum_SysAttributeType.Time.Noon);
            }
            else if (hours >= 13 && hours < 17)
            {
                ts = _Redis.GetI18nValue(Enum_SysAttributeType.Time.Afternoon);
            }
            else
            {
                ts = _Redis.GetI18nValue(Enum_SysAttributeType.Time.Evening);
            }

            return string.Format("{0},{1}", ts, _Redis.GetI18nValue(Enum_SysAttributeType.Misc.Welcomeback));
        }

        public async Task<RM_ApiResult> CurrentAdminInfo()
        {
            if (_CurrentAdmin != null)
            {
                if (!string.IsNullOrEmpty(_CurrentAdmin.Token))
                {
                    _Redis.DeleteRedisAttr("en", _CurrentAdmin.Token, Enum_RedisKey.AdminToken);
                }

                var result = new RM_AdminRole
                {
                    Id = "admin",
                    Name = "管理员"
                };

                if (_CurrentAdmin.IsSuper)
                {
                    //超级管理员
                    result.Permissions = await _DbContext.Queryable<TPermission>()
                                                         .Select(o => new RM_AdminPermissions
                                                         {
                                                             PermissionId = o.AuthName.ToLower()
                                                         }).ToListAsync();
                }
                else
                {
                    result.Permissions = await _DbContext.Queryable<TAdminpermissionrelation>().LeftJoin<TPermission>((t1, t2) => t1.PermissionId == t2.Id)
                                                         .Where((t1, t2) => t1.AdminId == _CurrentAdmin.Id)
                                                         .Select((t1, t2) => new RM_AdminPermissions
                                                         {
                                                             PermissionId = t2.AuthName.ToLower()
                                                         }).ToListAsync();
                }

                //添加权限缓存
                _Redis.SetRedisAttr("en", _CurrentAdmin.Token, result.Permissions, (DateTime)_CurrentAdmin.ExpireTime, Enum_RedisKey.AdminPowers);

                return _ResultHelper.BuildSuccess(new { role = result });
            }
            else
            {
                return _ResultHelper.BuildError();
            }
        }

        #endregion 用户登录相关

        #region 用户管理

        public async Task<RM_ApiResult> GetPage(Par_AdminPageBase par)
        {
            var exp = Expressionable.Create<TAdminInfo>()
                                    .And(o => o.Status == (int)Enum_BaseStatus.Working)
                                    .And(o => o.IsSuper == false)
                                    .AndIF(!string.IsNullOrWhiteSpace(par.KeyWord),
                                            o => o.AdminName.Contains(par.KeyWord));

            var where = exp.ToExpression();
            var datas = await GetPageByExp(where, par, o => o.CreateTime, OrderByType.Desc);
            datas.Datas.ForEach(item =>
            {
                item.AdminPwd = "";
            });
            return _ResultHelper.BuildSuccess(datas);
        }

        public async Task<RM_ApiResult> ResetPassWord(List<int> Keys)
        {
            var result = await Update(o => Keys.Contains(o.Id), o => new TAdminInfo { AdminPwd = _WebMiscConfig.ResetPassWord });

            if (result > 0)
            {
                return _ResultHelper.BuildSuccess();
            }
            else
            {
                return _ResultHelper.BuildError();
            }
        }

        public async Task<RM_ApiResult> ActionItem(Par_AdminInfo_Power par)
        {
            if (par.AdminName.IsNullOrEmpty())
            {
                return _ResultHelper.BuildActionError(Enum_SysAttributeType.Admin.LoginEmpty);
            }

            if (await Any(o => o.Id != par.Id && o.Status == (int)Enum_BaseStatus.Working && o.AdminName == par.AdminName))
            {
                return _ResultHelper.BuildError(Enum_SysAttributeType.Admin.DuplicateUserName);
            }

            var id = 0;

            var o = await Get(par.Id);
            if (o != null)
            {
                o.AdminName = par.AdminName;

                await Update(o);
                id = o.Id;
            }
            else
            {
                o = new TAdminInfo
                {
                    AdminName = par.AdminName,
                    AdminPwd = _WebMiscConfig.ResetPassWord,
                    Status = (int)Enum_BaseStatus.Working,
                    IsSuper = false,
                    IsModifyPassword = true,
                };

                id = await AddRId(o);
            }

            if (id > 0)
            {
                await _adminPermissionService.ActionPowers(par.Powers, id);

                return _ResultHelper.BuildSuccess(id);
            }
            else
            {
                return _ResultHelper.BuildError();
            }
        }

        public new async Task<RM_ApiResult> DeleteItem(int Key)
        {
            var data = await Get(Key);

            await Update(Key, o => new TAdminInfo { ExpireTime = DateTime.Now, Status = (int)Enum_AdminStatus.Stop });

            //删除用户redis
            _Redis.DeleteRedisAttr("en", data.Token, Enum_RedisKey.AdminToken);
            //删除权限redis
            _Redis.DeleteRedisAttr("en", data.Token, Enum_RedisKey.AdminPowers);

            return _ResultHelper.BuildActionSuccess();
        }

        public async Task<RM_ApiResult> ChangePwd(Par_AdminChangePwd par)
        {
            var oldpassword = md5Helper.CalculateMD5Hash(par.Old);
            var newpassword = md5Helper.CalculateMD5Hash(par.New);

            if (await Any(o => o.Id == _CurrentAdmin.Id && o.AdminPwd == oldpassword))
            {
                var result = await Update(o => o.Id == _CurrentAdmin.Id, o => new TAdminInfo { AdminPwd = newpassword, IsModifyPassword = false });

                if (result > 0)
                {
                    var data = await Get(_CurrentAdmin.Id);
                    // 重置密码后需重新登录
                    //删除用户redis
                    _Redis.DeleteRedisAttr("en", data.Token, Enum_RedisKey.AdminToken);
                    //删除权限redis
                    _Redis.DeleteRedisAttr("en", data.Token, Enum_RedisKey.AdminPowers);

                    return _ResultHelper.BuildActionSuccess();
                }
                else
                {
                    return _ResultHelper.BuildActionError();
                }
            }
            return _ResultHelper.BuildActionError(Enum_SysAttributeType.Admin.PassWordError);
        }

        public async Task<RM_ApiResult> ResetPassWord(int Keys)
        {
            var result = await Update(Keys, o => new TAdminInfo { AdminPwd = _WebMiscConfig.ResetPassWord, IsModifyPassword = true });

            if (result > 0)
            {
                var data = await Get(Keys);
                // 重置密码后需重新登录
                //删除用户redis
                _Redis.DeleteRedisAttr("en", data.Token, Enum_RedisKey.AdminToken);
                //删除权限redis
                _Redis.DeleteRedisAttr("en", data.Token, Enum_RedisKey.AdminPowers);

                return _ResultHelper.BuildActionSuccess();
            }
            else
            {
                return _ResultHelper.BuildActionError();
            }
        }

        #endregion 用户管理

        public void CreateTable(bool Backup = false, int StringDefaultLength = 50, params Type[] types)
        {
            Console.WriteLine(types);

            // 设置默认字符串长度
            _DbContext.CodeFirst.SetStringDefaultLength(StringDefaultLength);
            // 创建数据库
            _DbContext.DbMaintenance.CreateDatabase();

            // 备份表
            if (Backup)
            {
                _DbContext.CodeFirst.BackupTable().InitTables(types);
            }
            // 创建表
            else
            {
                _DbContext.CodeFirst.InitTables(types);
            }
        }

        public void SetI18n()
        {
            var i18n = _DbContext.Queryable<TI18n>().Where(o => o.Status == 1)
                                 .ToList();

            if (i18n.Count > 0)
            {
                foreach (var item in i18n)
                {
                    _Redis.SetRedisAttr("en", item.Key, item.En, Enum_RedisKey.SysAttribution);
                    _Redis.SetRedisAttr("tw", item.Key, item.Tw, Enum_RedisKey.SysAttribution);
                }
            }
        }
    }
}